package com.lang.generator.core.helper;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import com.lang.generator.common.constant.GlobalConstant;
import com.lang.generator.domain.dto.ContentDto;
import com.lang.generator.domain.dto.DataModelParseDto;
import com.lang.generator.domain.dto.TemplateDto;
import freemarker.cache.StringTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.stereotype.Component;
import org.springframework.ui.freemarker.SpringTemplateLoader;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.io.StringWriter;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 模板辅助
 *
 * @author Lang
 * @date 2022/11/19
 */
@Slf4j
@Component
public class TemplateHelper {



    /**
     * 解析文件
     */
    private Configuration fileCfg;

    /**
     * 解析字符串
     */
    private Configuration textCfg;

    @PostConstruct
    public void initConfiguration() {
        fileCfg = new Configuration(Configuration.VERSION_2_3_22);
        fileCfg.setTemplateLoader(new SpringTemplateLoader(new DefaultResourceLoader(), GlobalConstant.templatePath));
        fileCfg.setDefaultEncoding("UTF-8");

        textCfg = new Configuration(Configuration.VERSION_2_3_22);
        textCfg.setDefaultEncoding("UTF-8");
        textCfg.setTemplateLoader(new StringTemplateLoader());
    }


    /**
     * 模板字符串解析
     *
     * @param templateValue
     * @param dataModelParseDto
     * @return
     */
    public String parseTemplateText(String templateValue, DataModelParseDto dataModelParseDto) {
        return parseTemplate(null, templateValue, dataModelParseDto);
    }

    /**
     * 模板文件解析
     *
     * @param templatePath
     * @param dataModelParseDto
     * @return
     */
    public String parseTemplateFile(String templatePath, DataModelParseDto dataModelParseDto) {
        return parseTemplate(templatePath, null, dataModelParseDto);
    }

    /**
     * 模板解析
     *
     * @param templatePath
     * @param templateValue
     * @param dataModelDto
     * @return
     */
    private String parseTemplate(String templatePath, String templateValue, DataModelParseDto dataModelDto) {
        StringWriter stringWriter = new StringWriter();
        try {
            Template template;
            if (StrUtil.isNotBlank(templatePath)) {
                template = fileCfg.getTemplate(templatePath);
            } else if (StrUtil.isNotBlank(templateValue)) {
                template = new Template("", templateValue, textCfg);
            } else {
                return "";
            }
            template.process(dataModelDto, stringWriter);
        } catch (IOException ioException) {
            log.error("获取模板异常", ioException);
        } catch (TemplateException templateException) {
            log.error("模板解析异常", templateException);
        }
        return stringWriter.toString();
    }

    public ContentDto parseTemplate(TemplateDto templateDto, DataModelParseDto dataModelDto) {
        String contentPath = parseTemplateText(templateDto.getContentPath(), dataModelDto);
        String contentName = templateDto.getTemplateName().replace("Xxx", dataModelDto.getTableStructure().getClassNameUppercase());
        String contentValue = parseTemplateFile(templateDto.getTemplatePath(), dataModelDto);
        ContentDto contentDto = new ContentDto();
        contentDto.setValue(contentValue);
        contentDto.setFilePath(contentPath);
        contentDto.setFileName(contentName);
        return contentDto;
    }

    public void appendZipStream(ZipOutputStream zipOutputStream, ContentDto contentDto) {
        try {
            zipOutputStream.putNextEntry(new ZipEntry(contentDto.getFilePath()));
            IoUtil.writeUtf8(zipOutputStream, false, contentDto.getValue());
            zipOutputStream.flush();
            zipOutputStream.closeEntry();
        } catch (IOException e) {
            log.error("模板写入ZIP异常", e);
        }
    }

}
